// 将线程池改成单例的
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include "LockGuard.hpp"
#include "Thread.hpp"
#include <queue>
#include <functional>
using namespace std;

namespace ThreadNs {
    struct ThreadData {
        ThreadData (const string& threadname) 
            :_threadname(threadname)
        {
            
        }
        string _threadname;
    };

    const int default_num = 10;// 默认线程数量

    template <class T>
    class threadpool {
        private :
        threadpool(const int num = default_num) 
            :_thread_num(num)
        {
            // 初始化互斥锁和条件变量
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);
            // 创建指定数量的线程
            for (int i = 1; i <= _thread_num; i++) {
                string threadname = "thread" + to_string(i);
                ThreadData td(threadname);
                // thread<ThreadData> t(threadname, bind(&threadpool<T>::ThreadRun, this, placeholders::_1), td);
                // lg.LogMessage(Info, "%s create sucess!", threadname.c_str());
                // _threads.push_back(t);
                _threads.emplace_back(thread<ThreadData>(threadname, bind(&threadpool<T>::ThreadRun, this, placeholders::_1), td));
                lg.LogMessage(Info, "%s create sucess!", threadname.c_str());
            }
        }

        threadpool(const threadpool<T>&) = delete;
        threadpool<T>& operator=(const threadpool<T>&) = delete;
        public :
        static threadpool<T>* GetInstance(int num = default_num) {
            if (_inst == nullptr) {
                // 为了防止线程安全问题，所以我们需要加锁
                LockGuard lock(&_sig_mutex);
                if (_inst == nullptr) {
                    _inst = new threadpool<T>(num);
                }
            }

            return _inst;
        }


        void Push(const T& in) {
            // 先加锁
            {
                LockGuard lock(&_mutex);
                _q.push(in);
            }

            pthread_cond_signal(&_cond); // 唤醒一个线程
            cout << "唤醒一个线程……" << endl;
        }

        void Start() {
            for (auto& thread : _threads) {
                thread.Start();
                lg.LogMessage(Info, "%s is start!", thread.get_name().c_str());
            }
        }


        void ThreadRun(ThreadData& td) {
            T t;
            while (true) {
                {
                    {
                        // 先加锁
                        LockGuard lock(&_mutex);
                        while (_q.empty()) {
                            pthread_cond_wait(&_cond, &_mutex);
                        }
                        t = _q.front();
                        _q.pop();
                        // 处理任务                        
                    }
                    t();
                    // sleep(1);
                    // lg.LogMessage(Debug, "%s handle done a task: %s, result is: %s", td._threadname.c_str(), t.TaskToString().c_str(), \
                    // t.ResultToString().c_str());
                    // 唤醒其他线程
                }

            }
        }

        ~threadpool() {
            for (auto& thread : _threads) {
                
                thread.Join();
            }
        }



        private :
        queue<T> _q; // 任务队列
        vector<thread<ThreadData>> _threads; // 线程集合
        int _thread_num; // 线程数量
        pthread_mutex_t _mutex; // 互斥锁
        pthread_cond_t _cond; // 条件变量

        static pthread_mutex_t _sig_mutex; // 单例锁

        static threadpool<T>* _inst;
    };


    template<class T>
    threadpool<T>* threadpool<T>::_inst = nullptr;
    template <class T>
    pthread_mutex_t threadpool<T>::_sig_mutex = PTHREAD_MUTEX_INITIALIZER;

};